﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.Swagger;
using YSC_App_WebApi.RestClient;
using YSC_Data.BLL.DBContext;

namespace YSC_App_WebApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddMvcCore(option =>
            {
                option.Filters.Add(new TestAuthorizationFilter());
            }).AddAuthorization()
               .AddJsonFormatters();


            services.AddCors(options =>
            {
                options.AddPolicy("AllowAll",
                builder =>
                {
                    builder
                 .AllowAnyOrigin()
                 .AllowAnyMethod()
                 .AllowAnyHeader();
                });
            });


            services.AddAuthentication("Bearer")
                .AddJwtBearer("Bearer", options =>
                {
                    //http://localhost:5000
                    //http://yscoauth.cnfm.com.cn:8099
                    options.Authority = "http://yscoauth.cnfm.com.cn:8099";
                    // options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;

                    options.Audience = "api1";
                });

            #region Swagger
            //https://github.com/domaindrivendev/Swashbuckle.AspNetCore
            services.AddSwaggerGen(c =>
            {

                c.SwaggerDoc("v1", new Info { Title = "YSC API", Version = "v1" });
                c.DocInclusionPredicate((docName, description) => true);
                c.AddSecurityDefinition("Bearer", new ApiKeyScheme
                {
                    Description = "Authorization format : Bearer {token}",
                    Name = "Authorization",
                    In = "header",
                    Type = "apiKey"
                });//api界面新增authorize按钮

                //c.SwaggerDoc("v1", new Info
                //{
                //    Version = "v1",
                //    Title = "ToDo API",
                //    Description = "A simple example ASP.NET Core Web API",
                //    TermsOfService = "None",
                //    Contact = new Contact
                //    {
                //        Name = "",
                //        Email = string.Empty,
                //        Url = ""
                //    },
                //    License = new License
                //    {
                //        Name = "",
                //        Url = ""
                //    }
                //});

                //c.DocInclusionPredicate((docName, description) => true);
                //c.AddSecurityDefinition("Bearer", new ApiKeyScheme
                //{
                //    Description = "Authorization format : Bearer {token}",
                //    Name = "Authorization",
                //    In = "header",
                //    Type = "apiKey"
                //});//api界面新增authorize按钮

                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath, true);

                //接入identityserver
                //c.AddSecurityDefinition("oauth2", new OAuth2Scheme
                //{
                //    Flow = "implicit", // 只需通过浏览器获取令牌（适用于swagger）
                //    AuthorizationUrl = "http://localhost:5000/connect/authorize",//获取登录授权接口
                //    Scopes = new Dictionary<string, string> {
                //        { "YSC_OpenPlatform_API", "是否准许YSC_OpenPlatform_API访问" }//指定客户端请求的api作用域。 如果为空，则客户端无法访问
                //    }
                //});
                //c.OperationFilter<AuthResponsesOperationFilter>();
            });
            //_ = services.AddSwaggerGen(options =>
            //{
            //    options.SwaggerDoc("doc", new Swashbuckle.AspNetCore.Swagger.Info() { Title = "@XXX" });
            //    //为了兼容IISExpress，需添加AppDomain.CurrentDomain.BaseDirectory 
            //    options.IncludeXmlComments(AppDomain.CurrentDomain.BaseDirectory + "comment.xml");

            //    //添加文件上传按钮，另外api/action需添加特性[AddSwaggerFileUploadButton]
            //    //如果代码包含services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);那么这些代码就不需要了
            //    //<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="4.5.5" />
            //    //using Microsoft.AspNetCore.Mvc;
            //    //options.OperationFilter<AddFileParamTypesOperationFilter>();
            //});
            #endregion


            #region Scrutor
            //scrutor 注册
            //_ = services.Scan(scan => scan
            //    .FromAssemblyOf<Startup>()
            //        .AddClasses(classes => classes.AssignableTo(t => t.Name.Contains("Repository", StringComparison.OrdinalIgnoreCase)))
            //            .AsImplementedInterfaces()
            //            .WithTransientLifetime()

            //        .AddClasses(classes => classes.Where(t => t.Name.Contains("Service", StringComparison.OrdinalIgnoreCase)))
            //            .AsImplementedInterfaces()
            //            .WithScopedLifetime()


            //        .AddClasses(classes => classes.Where(t => t.Name.Contains("DbContext", StringComparison.OrdinalIgnoreCase)))
            //            .AsImplementedInterfaces()
            //            .WithScopedLifetime()
            //  );

            //_ = services.Scan(scan => scan
            //      .FromAssemblyOf<YSC_Services.BLL.Program>()
            //          .AddClasses(classes => classes.Where(t => t.Name.Contains("Services", StringComparison.OrdinalIgnoreCase)))
            //              .AsImplementedInterfaces()
            //              .WithScopedLifetime()
            // );


            // 自动地发现并注册指定的服务
            services.Scan(
                x =>
                {
                    var entryAssembly = Assembly.GetEntryAssembly();
                    var referencedAssemblies = entryAssembly.GetReferencedAssemblies().Select(Assembly.Load);
                    var assemblies = new List<Assembly> { entryAssembly }.Concat(referencedAssemblies);

                    x.FromAssemblies(assemblies)
                             .AddClasses(classes => classes.Where(t => t.Name.EndsWith("AppServices", StringComparison.OrdinalIgnoreCase)))
                            .AsImplementedInterfaces()
                            .WithScopedLifetime()


                            .AddClasses(classes => classes.Where(t => t.Name.EndsWith("BackstageServices", StringComparison.OrdinalIgnoreCase)))
                            .AsImplementedInterfaces()
                            .WithScopedLifetime()

                                  .AddClasses(classes => classes.Where(t => t.Name.EndsWith("DBContext", StringComparison.OrdinalIgnoreCase)))
                            .AsImplementedInterfaces()
                            .WithScopedLifetime()

                             .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Repository", StringComparison.OrdinalIgnoreCase)))
                            .AsImplementedInterfaces()
                            .WithScopedLifetime();
                });



            //EF上下文注册
            services.Scan(scan => scan
                 .AddTypes(typeof(EntityFrameworkDbContext))
                         .AsSelf()
                       .WithSingletonLifetime()
                     );

            #endregion
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseCors("AllowAll");
            app.UseStaticFiles();
            //  _ = app.UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/doc/swagger.json", null));
            _ = app.UseSwagger();
            _ = app.UseAuthentication();
            _ = app.UseHttpsRedirection();
            _ = app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
                c.OAuthClientId("api1_client");
                c.OAuthAppName("api1 描述"); // 描述
            });

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            _ = app.UseMvc();
        }
    }
}
